<?php
/**
 * 虚拟商品购买行为
 *
 * @好商城提供技术支持 授权请购买shopnc授权
 * @license    http://www.33hao.com
 * @link       交流群号：138182377
 */
defined('In33hao') or exit('Access Invalid!');

class buy_virtualLogic
{

    /**
     * 虚拟商品购买第一步，得到购买数据(商品、店铺、会员)
     * @param int $goods_id 商品ID
     * @param int $quantity 购买数量
     * @param int $member_id 会员ID
     * @return array
     */
    public function getBuyStep1Data($goods_id, $quantity, $member_id)
    {
        return $this->getBuyStepData($goods_id, $quantity, $member_id);
    }

    /**
     * 虚拟商品购买第二步，得到购买数据(商品、店铺、会员)
     * @param int $goods_id 商品ID
     * @param int $quantity 购买数量
     * @param int $member_id 会员ID
     * @return array
     */
    public function getBuyStep2Data($goods_id, $quantity, $member_id)
    {
        return $this->getBuyStepData($goods_id, $quantity, $member_id);
    }

    /**
     * 得到虚拟商品购买数据(商品、店铺、会员)
     * @param int $goods_id 商品ID
     * @param int $quantity 购买数量
     * @param int $member_id 会员ID
     * @return array
     */
    public function getBuyStepData($goods_id, $quantity, $member_id)
    {
        $model_goods = Model('goods');
        $goods_id = intval($goods_id);
        $goods_info = $model_goods->getVirtualGoodsOnlineInfoByID($goods_id);
        if (empty($goods_info)) {
            return callback(false, '该商品不符合购买条件，可能的原因有：下架、不存在、过期等');
        }
        if ($goods_info['store_id'] == $_SESSION['store_id']) {
            return callback(false, '不允许自己店铺的商品');
        }

        if ($goods_info['virtual_limit'] > $goods_info['goods_storage']) {
            $goods_info['virtual_limit'] = $goods_info['goods_storage'];
        }
        //处理商品消费者保障服务信息
        $goods_list = $model_goods->getGoodsContract(array(0 => $goods_info));
        $goods_info = $goods_list[0];

        //取得抢购信息
        $goods_info = $this->_getGroupbuyInfo($goods_info);

        $quantity = abs(intval($quantity));
        $quantity = $quantity == 0 ? 1 : $quantity;
        $quantity = $quantity > $goods_info['virtual_limit'] ? $goods_info['virtual_limit'] : $quantity;
        if ($quantity > $goods_info['goods_storage']) {
            return callback(false, '该商品库存不足');
        }
        $goods_info['quantity'] = $quantity;
        $goods_info['goods_total'] = ncPriceFormat($goods_info['goods_price'] * $goods_info['quantity']);
        $goods_info['goods_image_url'] = cthumb($goods_info['goods_image'], 240, $goods_info['store_id']);

        //规格
        $_tmp_name = unserialize($goods_info['spec_name']);
        $_tmp_value = unserialize($goods_info['goods_spec']);
        if (is_array($_tmp_name) && is_array($_tmp_value)) {
            $_tmp_name = array_values($_tmp_name);
            $_tmp_value = array_values($_tmp_value);
            $new_array = [];
            foreach ($_tmp_name as $sk => $sv) {
                $new_array['goods_spec'] .= $sv . '：' . $_tmp_value[$sk] . '，';
            }
            $goods_info['goods_spec'] = rtrim($new_array['goods_spec'], '，');
        } else {
            $goods_info['goods_spec'] = null;
        }

        $return = array();
        $return['goods_info'] = $goods_info;
        $return['store_info'] = Model('store')->getStoreOnlineInfoByID($goods_info['store_id'], 'store_name,store_id,member_id');
        $return['member_info'] = Model('member')->getMemberInfoByID($member_id);

        return callback(true, '', $return);
    }

    /**
     * 虚拟商品购买第三步
     * @param array $post 接收POST数据，必须传入goods_id:商品ID，quantity:购买数量,buyer_phone:接收手机,buyer_msg:买家留言
     * @param int $member_id
     * @return array
     */
    public function buyStep3($post, $member_id)
    {
        $result = $this->getBuyStepData($post['goods_id'], $post['quantity'], $member_id);
        if (!$result['state']) return $result;

        $goods_info = $result['data']['goods_info'];
        $member_info = $result['data']['member_info'];

        //应付总金额计算
        $pay_total = $goods_info['goods_price'] * $goods_info['quantity'];
        $store_id = $goods_info['store_id'];
        $store_goods_total_list = array($store_id => $pay_total);
        $pay_total = $store_goods_total_list[$store_id];

        //整理数据
        $input = array();
        $input['quantity'] = $goods_info['quantity'];
        $input['buyer_phone'] = $post['buyer_phone'];
        $input['buyer_msg'] = $post['buyer_msg'];
        $input['pay_total'] = $pay_total;
        $input['order_from'] = $post['order_from'];
        $input['my_store_id'] = isset($post['my_store_id']) ? $post['my_store_id'] : 0;
        $input['use_points'] = intval($post['use_points']);   //兑换商品使用积分抵扣
        try {

            $model_goods = Model('goods');
            //开始事务
            $model_goods->beginTransaction();

            //生成订单
            $order_info = $this->_createOrder($input, $goods_info, $member_info);
            if (!empty($post['password'])) {
                if ($member_info['member_paypwd'] != '' && $member_info['member_paypwd'] == md5($post['password'])) {
                    //充值卡支付
                    if (!empty($post['rcb_pay'])) {
                        $order_info = $this->rcbPay($order_info, $post, $member_info);
                    }
                    //预存款支付
                    if (!empty($post['pd_pay'])) {
                        $this->pdPay($order_info, $post, $member_info);
                    }
                }
            }

            //提交事务
            $model_goods->commit();

        } catch (Exception $e) {

            //回滚事务
            $model_goods->rollback();
            return callback(false, $e->getMessage());
        }

        //变更库存和销量
        QueueClient::push('createOrderUpdateStorage', array($goods_info['goods_id'] => $goods_info['quantity']));

        //更新抢购信息
        $this->_updateGroupBuy($goods_info);

        //发送兑换码到手机
        $param = array('order_id' => $order_info['order_id'], 'buyer_id' => $member_id, 'buyer_phone' => $order_info['buyer_phone'], 'goods_name' => $order_info['goods_name']);
        QueueClient::push('sendVrCode', $param);

        //生成交易快照
        QueueClient::push('createVrSphot', array('order_id' => $order_info['order_id'], 'goods_id' => $goods_info['goods_id']));

        return callback(true, '', array('order_id' => $order_info['order_id'], 'order_sn' => $order_info['order_sn']));
    }

    /**
     * 生成订单
     * @param array $input 表单数据
     * @param unknown $goods_info 商品数据
     * @param unknown $member_info 会员数据
     * @throws Exception
     * @return array
     */
    private function _createOrder($input, $goods_info, $member_info)
    {
        extract($input);
        $model_vr_order = Model('vr_order');

        //存储生成的订单,函数会返回该数组
        $order_list = array();

        $order = array();
        $order_code = array();

        $goods_class = Model('goods_class')->getGoodsClassList(array('gc_id' => $goods_info['gc_id']), "commis_rate,isshow,is_open");

        //判断店铺类型
        $store_info = Model('store')->getStoreInfoByID($goods_info['store_id']);
//-------------------------------------获取分销层级比例start------------------------------------------------
        $settings = Model('setting')->getListSetting();
        //商圈店
        $fx_hy_level_one = $settings['fx_hy_level_one'];  //一级分销比例
        $fx_hy_level_two = $settings['fx_hy_level_two']; //二级分销比例

        $invite_one = 0;
        $invite_two = 0;

        $model_member = Model('member');
        $model_agent = Model('agent');
        if ($member_info['lev1']) {
            $invite_one = $fx_hy_level_one;
            if ($member_info['lev2']) {
                $invite_two = $fx_hy_level_two;
            }
        }

//-------------------------------------获取分销层级比例end------------------------------------------------

        $goods_common_info = Model('goods')->getGoodsCommonInfoByID($goods_info['goods_commonid'], 'goods_commonid');
        $order['goods_costprice'] = $goods_common_info['goods_costprice'];
        $order['order_sn'] = $this->_makeOrderSn($member_info['member_id']);
        $order['store_id'] = $goods_info['store_id'];
        $order['store_name'] = $goods_info['store_name'];
        $order['buyer_id'] = $member_info['member_id'];
        $order['buyer_name'] = $member_info['member_name'];
        $order['buyer_phone'] = $input['buyer_phone'];
        $order['buyer_msg'] = $input['buyer_msg'];
        $order['add_time'] = TIMESTAMP;
        $order['order_state'] = ORDER_STATE_NEW;
        $order['order_amount'] = $pay_total;
        $order['goods_id'] = $goods_info['goods_id'];
        $order['goods_name'] = $goods_info['goods_name'];
        $order['goods_price'] = $goods_info['goods_price'];
        $order['goods_num'] = $input['quantity'];
        $order['goods_image'] = $goods_info['goods_image'];
        $order['commis_rate'] = $goods_class[0]['commis_rate'];
        $order['gc_id'] = $goods_info['gc_id'];
        $order['vr_indate'] = $goods_info['virtual_indate'];
        $order['vr_invalid_refund'] = $goods_info['virtual_invalid_refund'];
        $order['order_from'] = $input['order_from'];
        $order['order_type'] = $store_info['store_class'];  //订单类型：0.平台店铺订单 1.商圈店铺订单
        if ($goods_info['ifgroupbuy'] == 1) {
            $order['order_promotion_type'] = 1;
            $order['promotions_id'] = $goods_info['groupbuy_id'];
        }
        $order['use_points'] = $input['use_points'];
        //积分抵扣
        if ($order['use_points']) {
            $order['order_amount'] = $order['order_amount'] -  sprintf("%.1f", $input['use_points']/$settings['points_dikou']);   //抵扣后总金额
            //减扣积分
            Model('member')->editMember(['member_id'=>$member_info['member_id']],['member_points' =>array('exp','member_points-'.$input['use_points'])]);
        }

        //记录消费者保障服务
        $contract_itemid_arr = $goods_info['contractlist'] ? array_keys($goods_info['contractlist']) : array();
        $order['goods_contractid'] = $contract_itemid_arr ? implode(',', $contract_itemid_arr) : '';

        $order['goods_spec'] = $goods_info['goods_spec'];



        //小店ID
        $order['my_store_id'] = $input['my_store_id'] ? $input['my_store_id'] : 0;

//---------------------------------------------------分销佣金处理start-----------------------------------------------------
        //商品总利润
        $total_goods_rates = $order['goods_num'] * $goods_info['goods_rates'];

        //会员各层级分销金额
        $order['invite_rates'] = doubleval($total_goods_rates * $invite_one / 100);
        $order['invite_rates_two'] = doubleval($total_goods_rates * $invite_two / 100);
        //开店套餐佣金
        if ($invite_one && !$goods_class[0]['isshow'] && $goods_class[0]['is_open']) {
            //根据套餐价格判断开店类型获取相应等级的开店分销比例
            if ($goods_info['goods_price'] == $settings['fx_st_tc_one']) {
                $invite_one = $settings['fx_st_one_open_one'];
                $invite_two = $settings['fx_st_one_open_two'];
            }
            if ($goods_info['goods_price'] == $settings['fx_st_tc_two']) {
                $invite_one = $settings['fx_st_two_open_one'];
                $invite_two = $settings['fx_st_two_open_two'];
            }
            if ($goods_info['goods_price'] == $settings['fx_st_tc_three']) {
                $invite_one = $settings['fx_st_three_open_one'];
                $invite_two = $settings['fx_st_three_open_two'];
            }
            if ($goods_info['goods_price'] == $settings['fx_st_tc_four']) {
                $invite_one = $settings['fx_st_four_open_one'];
                $invite_two = $settings['fx_st_four_open_two'];
            }
            $order['invite_rates'] = doubleval($goods_info['goods_price'] * $invite_one / 100);
            $order['invite_rates_two'] = doubleval($goods_info['goods_price'] * $invite_two / 100);
        }
        if (!$store_info['store_class'] && $order['my_store_id']) {
            //根据店铺类型获取相应等级的小店佣金比例
            $model_store = Model('store');
            $store_info = $model_store->getStoreInfoByID($goods_info['my_store_id']);
            $fx_st_store = 0;
            if ($store_info['type'] == 1) {
                $fx_st_store = $settings['fx_st_one'];
            }
            if ($store_info['type'] == 2) {
                $fx_st_store = $settings['fx_st_two'];
            }
            if ($store_info['type'] == 3) {
                $fx_st_store = $settings['fx_st_three'];
            }
            if ($store_info['type'] == 4) {
                $fx_st_store = $settings['fx_st_four'];
            }
            //小店分销金额
            $order['store_rates'] = doubleval($total_goods_rates * $fx_st_store / 100);
        }
//------------------------------------------------分销佣金处理end----------------------------------------------------------
        $order_id = $model_vr_order->addOrder($order);
        if (!$order_id) {
            throw new Exception('订单保存失败');
        }
        $order['order_id'] = $order_id;

        // 提醒[库存报警]
        if ($goods_info['goods_storage_alarm'] >= ($goods_info['goods_storage'] - $input['quantity'])) {
            $param = array();
            $param['common_id'] = $goods_info['goods_commonid'];
            $param['sku_id'] = $goods_info['goods_id'];
            QueueClient::push('sendStoreMsg', array('code' => 'goods_storage_alarm', 'store_id' => $goods_info['store_id'], 'param' => $param));
        }

        return $order;
    }

    /**
     * 生成支付单编号(两位随机 + 从2000-01-01 00:00:00 到现在的秒数+微秒+会员ID%1000)，该值会传给第三方支付接口
     * 长度 =2位 + 10位 + 3位 + 3位  = 18位
     * 1000个会员同一微秒提订单，重复机率为1/100
     * @return string
     */
    private function _makeOrderSn($member_id)
    {
        return mt_rand(10, 99)
        . sprintf('%010d', time() - 946656000)
        . sprintf('%03d', (float)microtime() * 1000)
        . sprintf('%03d', (int)$member_id % 1000);
    }

    /**
     * 更新抢购购买人数和数量
     */
    private function _updateGroupBuy($goods_info)
    {
        if ($goods_info['ifgroupbuy'] && $goods_info['groupbuy_id']) {
            $groupbuy_info = array();
            $groupbuy_info['groupbuy_id'] = $goods_info['groupbuy_id'];
            $groupbuy_info['quantity'] = $goods_info['quantity'];
            QueueClient::push('editGroupbuySaleCount', $groupbuy_info);
        }
    }

    /**
     * 充值卡支付
     * 如果充值卡足够就单独支付了该订单，如果不足就暂时冻结，等API支付成功了再彻底扣除
     */
    public function rcbPay($order_info, $input, $buyer_info)
    {
        if ($order_info['order_state'] == ORDER_STATE_PAY) return $order_info;
        $available_rcb_amount = floatval($buyer_info['available_rc_balance']);

        if ($available_rcb_amount <= 0) return $order_info;
        $model_vr_order = Model('vr_order');
        $model_pd = Model('predeposit');

        $order_amount = floatval($order_info['order_amount']);
        $data_pd = array();
        $data_pd['member_id'] = $buyer_info['member_id'];
        $data_pd['member_name'] = $buyer_info['member_name'];
        $data_pd['amount'] = $order_amount;
        $data_pd['order_sn'] = $order_info['order_sn'];

        if ($available_rcb_amount >= $order_amount) {

            // 预存款立即支付，订单支付完成
            $model_pd->changeRcb('order_pay', $data_pd);
            $available_rcb_amount -= $order_amount;

            // 订单状态 置为已支付
            $data_order = array();
            $order_info['order_state'] = $data_order['order_state'] = ORDER_STATE_PAY;
            $order_info['payment_time'] = $data_order['payment_time'] = TIMESTAMP;
            $order_info['payment_code'] = $data_order['payment_code'] = 'predeposit';
            $order_info['rcb_amount'] = $data_order['rcb_amount'] = $order_amount;
            $result = $model_vr_order->editOrder($data_order, array('order_id' => $order_info['order_id']));
            if (!$result) {
                throw new Exception('订单更新失败');
            }

            //发放兑换码
            $insert = $model_vr_order->addOrderCode($order_info);
            //处理返佣
            $this->brokerageBill($order_info);
            //发送兑换码到手机
            $param = array('order_id' => $order_info['order_id'], 'buyer_id' => $order_info['buyer_id'], 'buyer_phone' => $order_info['buyer_phone']);
            QueueClient::push('sendVrCode', $param);
            // 支付成功发送店铺消息
            $param = array();
            $param['code'] = 'new_order';
            $param['store_id'] = $order_info['store_id'];
            $param['param'] = array(
                'order_sn' => $order_info['order_sn']
            );
            QueueClient::push('sendStoreMsg', $param);
            if (!$insert) {
                throw new Exception('兑换码发送失败');
            }

        } else {

            //暂冻结预存款,后面还需要 API彻底完成支付
            $data_pd['amount'] = $available_rcb_amount;
            $model_pd->changeRcb('order_freeze', $data_pd);
            //预存款支付金额保存到订单
            $data_order = array();
            $order_info['rcb_amount'] = $data_order['rcb_amount'] = $available_rcb_amount;
            $result = $model_vr_order->editOrder($data_order, array('order_id' => $order_info['order_id']));
            if (!$result) {
                throw new Exception('订单更新失败');
            }
        }
        return $order_info;
    }

    /**
     * 预存款支付
     * 如果预存款足够就单独支付了该订单，如果不足就暂时冻结，等API支付成功了再彻底扣除
     */
    public function pdPay($order_info, $input, $buyer_info)
    {
        if ($order_info['order_state'] == ORDER_STATE_PAY) return $order_info;

        $available_pd_amount = floatval($buyer_info['available_predeposit']);
        if ($available_pd_amount <= 0) return $order_info;

        $model_vr_order = Model('vr_order');
        $model_pd = Model('predeposit');

        $order_amount = floatval($order_info['order_amount']) - floatval($order_info['rcb_amount']);
        $data_pd = array();
        $data_pd['member_id'] = $buyer_info['member_id'];
        $data_pd['member_name'] = $buyer_info['member_name'];
        $data_pd['amount'] = $order_amount;
        $data_pd['order_sn'] = $order_info['order_sn'];

        if ($available_pd_amount >= $order_amount) {

            //预存款立即支付，订单支付完成
            $model_pd->changePd('order_pay', $data_pd);
            $available_pd_amount -= $order_amount;

            //下单，支付被冻结的充值卡
            $pd_amount = floatval($order_info['rcb_amount']);
            if ($pd_amount > 0) {
                $data_pd = array();
                $data_pd['member_id'] = $buyer_info['member_id'];
                $data_pd['member_name'] = $buyer_info['member_name'];
                $data_pd['amount'] = $pd_amount;
                $data_pd['order_sn'] = $order_info['order_sn'];
                $model_pd->changeRcb('order_comb_pay', $data_pd);
            }

            // 订单状态 置为已支付
            $data_order = array();
            $order_info['order_state'] = $data_order['order_state'] = ORDER_STATE_PAY;
            $order_info['payment_time'] = $data_order['payment_time'] = TIMESTAMP;
            $order_info['payment_code'] = $data_order['payment_code'] = 'predeposit';
            $order_info['pd_amount'] = $data_order['pd_amount'] = $order_amount;
            $result = $model_vr_order->editOrder($data_order, array('order_id' => $order_info['order_id']));
            if (!$result) {
                throw new Exception('订单更新失败');
            }

            //发放兑换码
            $model_vr_order->addOrderCode($order_info);
            //处理返佣
            $this->brokerageBill($order_info);
            //发送兑换码到手机
            $param = array('order_id' => $order_info['order_id'], 'buyer_id' => $order_info['buyer_id'], 'buyer_phone' => $order_info['buyer_phone']);
            QueueClient::push('sendVrCode', $param);
            // 支付成功发送店铺消息
            $param = array();
            $param['code'] = 'new_order';
            $param['store_id'] = $order_info['store_id'];
            $param['param'] = array(
                'order_sn' => $order_info['order_sn']
            );
            QueueClient::push('sendStoreMsg', $param);

        } else {

            //暂冻结预存款,后面还需要 API彻底完成支付
            $data_pd['amount'] = $available_pd_amount;
            $model_pd->changePd('order_freeze', $data_pd);
            //预存款支付金额保存到订单
            $data_order = array();
            $order_info['pd_amount'] = $data_order['pd_amount'] = $available_pd_amount;
            $result = $model_vr_order->editOrder($data_order, array('order_id' => $order_info['order_id']));
            if (!$result) {
                throw new Exception('订单更新失败');
            }
        }
        return $order_info;
    }

    /**
     * 线下预存款支付
     * 如果预存款足够就单独支付了该订单，如果不足就暂时冻结，等API支付成功了再彻底扣除
     */
    public function offline_pdPay($order_info, $input, $buyer_info)
    {
        if ($order_info['order_state'] == ORDER_STATE_PAY) return $order_info;

        $available_pd_amount = floatval($buyer_info['available_predeposit']);
        if ($available_pd_amount <= 0) return $order_info;

        $model_offline_order = Model('offline_order');
        $model_pd = Model('predeposit');

        $order_amount = floatval($order_info['order_amount']);
        $data_pd = array();
        $data_pd['member_id'] = $buyer_info['member_id'];
        $data_pd['member_name'] = $buyer_info['member_name'];
        $data_pd['amount'] = $order_amount;
        $data_pd['order_sn'] = $order_info['order_sn'];

        if ($available_pd_amount >= $order_amount) {

            //预存款立即支付，订单支付完成
            $model_pd->changePd('order_pay', $data_pd);

            // 订单状态 置为已支付
            $data_order = array();
            $order_info['order_state'] = $data_order['order_state'] = ORDER_STATE_PAY;
            $order_info['payment_time'] = $data_order['payment_time'] = TIMESTAMP;
            $order_info['payment_code'] = $data_order['payment_code'] = 'predeposit';
            $order_info['pd_amount'] = $data_order['pd_amount'] = $order_amount;
            $result = $model_offline_order->editOrder($data_order, array('order_id' => $order_info['order_id']));
            if (!$result) {
                throw new Exception('订单更新失败');
            }

            //处理返佣
           brokerageBill($order_info);
            // 支付成功发送店铺消息
            $param = array();
            $param['code'] = 'new_order';
            $param['store_id'] = $order_info['store_id'];
            $param['param'] = array(
                'order_sn' => $order_info['order_sn']
            );
            QueueClient::push('sendStoreMsg', $param);

        } else {

            //暂冻结预存款,后面还需要 API彻底完成支付
            $data_pd['amount'] = $available_pd_amount;
            $model_pd->changePd('order_freeze', $data_pd);
            //预存款支付金额保存到订单
            $data_order = array();
            $order_info['pd_amount'] = $data_order['pd_amount'] = $available_pd_amount;
            $result = $model_offline_order->editOrder($data_order, array('order_id' => $order_info['order_id']));
            if (!$result) {
                throw new Exception('订单更新失败');
            }
        }
        return $order_info;
    }

    /**
     * 取得抢购信息
     * @param array $goods_info
     * @return array
     */
    private function _getGroupbuyInfo($goods_info = array())
    {
        if (!C('groupbuy_allow') || empty($goods_info) || !is_array($goods_info)) return $goods_info;

        $groupbuy_info = Model('groupbuy')->getGroupbuyInfoByGoodsCommonID($goods_info['goods_commonid']);
        if (empty($groupbuy_info)) return $goods_info;
        // 虚拟抢购数量限制
        if ($groupbuy_info['upper_limit'] > 0 && $groupbuy_info['upper_limit'] < $goods_info['virtual_limit']) {
            $goods_info['virtual_limit'] = $groupbuy_info['upper_limit'];
        }
        $goods_info['goods_price'] = $groupbuy_info['groupbuy_price'];
        $goods_info['groupbuy_id'] = $groupbuy_info['groupbuy_id'];
        $goods_info['ifgroupbuy'] = true;

        return $goods_info;
    }

    //会员，小店分销即时结算
    public function brokerageBill($order_info)
    {
        addPointsLog($order_info);
    }

}